build and test on FreeBSD - #705
Merged
Merged
Conversation
Adds a FreeBSD job on GitHub Actions, plus the changes needed to make it pass. The Cirrus FreeBSD task last ran on 2026-04-01 and reported neutral rather than red before that, so none of this was visible.
The FreeBSD job on this branch failed to compile typed-fuse-core:
error[E0425]: cannot find value `ENODATA` in crate `libc`
--> typed-fuse-core/src/errno.rs:21:44
|
21 | pub const ENODATA: Errno = Errno(libc::ENODATA);
| ^^^^^^^ not found in `libc`
vgough/typed-fuse#3 fixed that, along with the rest of what this
branch needs from typed-fuse on FreeBSD, and was merged two minutes
after that build ran. Cargo.lock still pinned the git dependency at
dd70e27, from before the merge, so re-running the job would keep
building the old tree.
This moves the three git+ source lines to d4ec8f3, the current
typed-fuse main. Nothing else changes: every Cargo.toml in
typed-fuse is byte-identical between dd70e27 and d4ec8f3, so the
dependency graph is the same and only the pinned revision moves.
There was a problem hiding this comment.
Pull request overview
Adds first-class FreeBSD CI to the Rust EncFS port and fixes a handful of FreeBSD-specific portability gaps (xattr errno, xattr name encoding, test platform gating, and protobuf toolchain discovery) so the project can build and run its full test suite under FreeBSD in GitHub Actions.
Changes:
- Add a GitHub Actions workflow that boots a FreeBSD VM under QEMU and runs clippy/build/test + live mount tests.
- Make xattr handling portable across Linux/FreeBSD by switching stored xattr-name base64 encoding to URL-safe (with legacy-read fallback) and using
ENOATTRinstead ofENODATA. - Adjust tests to work on FreeBSD (mount detection, xattr backing-name listing, and symlink-permission expectations) and update build.rs to avoid vendored-protoc assumptions on non-supported OSes.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/freebsd.yml |
New FreeBSD CI workflow running clippy/build/test/live-mount in a VM. |
build.rs |
Stop panicking when vendored protoc is unavailable; fall back to PATH. |
src/fs.rs |
Use new xattr-name codec + legacy fallback when reading/removing old names. |
src/reverse_fs.rs |
Use shared xattr-name codec and ENOATTR for missing-xattr semantics. |
src/xattr_name.rs |
New helper module for URL-safe xattr name encoding/decoding + unit tests. |
src/lib.rs |
Export the new xattr_name module. |
tests/xattr_test.rs |
FreeBSD-aware backing xattr listing + improved failure diagnostics. |
tests/permissions_test.rs |
Exclude FreeBSD from symlink-mode assertions that don’t hold on BSDs. |
tests/live/mod.rs |
Use mount(8) parsing on FreeBSD (no /proc) like macOS. |
Cargo.lock |
Update typed-fuse git revision to a FreeBSD-fixing commit. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
vgough
reviewed
Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Cirrus FreeBSD task last ran on 2026-04-01. Before that it had
failed on every commit since the Rust port landed -- 28 runs, none green
-- and allow_failures: true reported each one as neutral, so nothing
surfaced. .cirrus.yml was last edited on 2026-07-25, after it had
already stopped running.
This adds .github/workflows/freebsd.yml, shaped like ci.yml: the same
clippy, build, test and live-mount sequence. The VM boots under QEMU on
an ordinary ubuntu-latest runner, so there is no service, no dedicated
runner and no compute credits.
Package names come from the pkg database on the box rather than from
memory: fusefs-libs3 supplies fuse3.pc 3.18.1, protobuf supplies protoc,
llvm supplies the libclang bindgen needs, and fusefs.ko is already in
GENERIC so nothing has to kldload it. .cirrus.yml installs fusefs-libs,
which is FUSE 2 and carries no fuse3.pc, so that task could not have
built even while it was still running.
build.rs
protoc-bin-vendored ships binaries for Linux, macOS and Windows only, so
protoc_bin_path() returns Err on FreeBSD and .expect() panics. Leaving
PROTOC unset there lets prost-build find protoc on PATH instead.
src/reverse_fs.rs
Four uses of libc::ENODATA, which FreeBSD does not define. Every one
means "extended attribute not found", so they become Errno::ENOATTR,
which typed-fuse already gates: on Linux that IS libc::ENODATA, so the
change is bit-identical there.
the xattr name encoding -- the one worth reading
Stored attribute names are base64 of the encrypted name, and the
standard alphabet contains '/', which FreeBSD will not accept in an
attribute name. Four names differing in a single character:
Of the six distinct names this repo's own xattr tests generate, exactly
the two containing '/' are the two whose setxattr returned EINVAL:
Ten of the names contained '+' and all stored fine. So on FreeBSD
roughly a third of extended attributes cannot be stored at all.
New names use the URL-safe alphabet, which spells the two disputed
characters '-' and '_'. Reads accept either, and getxattr and
removexattr fall back to the old spelling, so attributes written by
earlier builds stay reachable. The alphabets differ only in those four
characters, so a string that decodes under both contains none of them
and yields the same bytes either way: trying one and then the other
cannot return the wrong plaintext.
Two things this does not touch. Filenames go through
SslCipher::filename_base64_encode, which uses encfs's own alphabet, not
this one. And there is no compatibility to keep with the C++ encfs: it
passed attribute names to the backing file unchanged, so the encrypted
and encoded scheme has only ever existed in this port.
tests
tests/live/mod.rs defined mountinfo_has_mount for Linux and macOS only.
FreeBSD has no /proc either and its mount(8) prints the same
" on (, ...)" shape, so it joins the macOS
arm.
tests/xattr_test.rs read the backing names with llistxattr; FreeBSD gets
an extattr_list_link arm. There the namespace is not part of the name,
so what is stored is "encfs.", and the assertion says so instead of
being made to look uniform.
tests/permissions_test.rs asserted symlink mode 0o777, already excluding
macOS. Linux fixes those bits and ignores them; the BSDs give symlinks
real mode bits -- FreeBSD ships lchmod(2), "similar to chmod() but does
not follow symbolic links" -- and report 0o755, so FreeBSD joins the
exclusion.
Verified
Linux, this branch as it stands, under ci.yml: 215 tests across every
binary, 0 failed, including 29 live mount tests. No companion change
needed for this half.
https://github.com/neilpang/encfs/actions/runs/31366219652
FreeBSD 15.1: build, clippy -D warnings, 5/5 xattr, 4/4 permissions,
29/29 live mount. That run used these source files byte for byte plus a
temporary Cargo.toml patch pointing typed-fuse at the companion branch;
the patch is not in this PR.
https://github.com/neilpang/encfs/actions/runs/31364870397
Sequencing
The FreeBSD job goes green once vgough/typed-fuse#3 is in. Without it
the job stops here:
Compiling typed-fuse v0.6.0 (https://github.com/vgough/typed-fuse#dd70e273)
error[E0425]: cannot find value
ENODATAin cratelibchttps://github.com/neilpang/encfs/actions/runs/31366219628
typed-fuse does not build on FreeBSD today: no l*xattr syscalls, an
ungated ENODATA, a missing struct flock field, and a fuse_session_new
that libfuse 3.17 turned into a macro. Cargo.toml tracks its default
branch with no rev pin, so this picks the fix up on its own.
Two loose ends, yours to call: .cirrus.yml is dead weight now, and
ci.yml pins actions/checkout@v4 while v7 is current.
Written with the help of Claude; I read and tested all of it.